<?php
/**
 * Description: 鉴权钩子
 *
 * @author      Eden
 * @datetime    2016/11/23 23:10
 * @copyright   Beijing CmsTop Technology Co.,Ltd.
 */

class Verify
{

    // 访问超时时间
    const ASK_TIME = 0;

    // CI Controller
    private $CI;

    // 签权 Secret
    private $secret = '202cb962ac59075b964b07152d234b70';

    // API 接口配置
    private $conf = array();

    // 请求参数
    private $params = array();

    /**
     * 构造方法
     */
    public function __construct()
    {
        $this->CI = get_instance();
        $this->_checkCofig();
    }

    /**
     * 检查配置信息
     * @return bool
     */
    private function _checkCofig()
    {
        try {
            $this->conf = $this->CI->config->item('api');
            if (!empty($this->conf['params']) && !empty($this->conf['interface'])) {
                return true;
            }
        } catch (PDOException $e) {}

        $this->CI->output->send(array(
            'state' => false,
            'error' => 'API 配置错误'
        ));
    }

    /**
     * 验证鉴权
     */
    public function check()
    {
        $this->_checkNeedsParams()
            ->_checkVersionAndInterface()
            ->_checkAskTime();
            // ->_checkToken();
    }

    /**
     * 验证签名
     * @return bool
     */
    private function _checkToken()
    {
        $send['state'] = false;
        do {
            unset($this->params['sub']);
            $token = $this->params['token'];

            if (empty($token)) {
                $send['error'] = '签名错误';
                break;
            }

            unset($this->params['token']);
            ksort($this->params);
            $query = http_build_query($this->params, '_', '&', PHP_QUERY_RFC3986);
            $sign = md5(md5($query) . $this->secret . $this->params['time']);

            if ($sign === $token) {
                return true;
            } else {
                $send['error'] = '签名错误';
            }

        } while(false);

        $this->CI->output->send($send);
    }

    /**
     * 验证请求时间
     * @return $this
     */
    private function _checkAskTime()
    {
        if (self::ASK_TIME !== 0) {
            $time = $this->params['time'];
            if (!is_numeric($time) || intval($time) === 0) {
                $this->CI->output->send(array(
                    'state' => false,
                    'error' => '请求时间参数错误'
                ));
            }

            if ((time() - $time) > self::ASK_TIME) {
                $this->CI->output->send(array(
                    'state' => false,
                    'error' => '请求超时'
                ));
            }
        }

        return $this;
    }

    /**
     * 检查必要参数
     * @return $this
     */
    private function _checkNeedsParams()
    {
        $send['state'] = false;
        $this->gets = !empty($this->CI->input->get()) ? $this->CI->input->get() : array();
        $this->posts = !empty($this->CI->input->post()) ? $this->CI->input->post() : array();

        do {

            $this->params = $this->gets + $this->posts;
            $needsParams = $this->conf['params'];

            if (!empty($needsParams)) foreach($needsParams as $param) {
                if ( ! array_key_exists($param, $this->params)) {
                    $send['error'] = '缺少必要参数';
                    break 2;
                }
            }

            return $this;

        } while(false);

        $this->CI->output->send($send);
    }

    /**
     * 验证接口版本和接口名称
     * @return $this
     */
    private function _checkVersionAndInterface()
    {
        $send['state'] = false;
        $version = $this->CI->uri->segment(1);
        $interface = $this->CI->uri->segment(2);
        $module = $this->params['module'];
        $apis = $this->conf['interface'];

        do {

            if (empty($version) || empty($interface)) {
                $send['error'] = '接口错误';
                break;
            }

            if ( ! array_key_exists($interface, $apis)) {
                $send['error'] = '接口错误';
                break;
            }

            if (! array_key_exists($version, $apis[$interface]['version'])) {
                $send['error'] = '接口版本错误';
                break;
            }

            if (! in_array($module, $apis[$interface]['modules'])) {
                $send['error'] = '模块错误';
                break;
            }

            return $this;

        } while(false);

        $this->CI->output->send($send);

    }


}
